昨天我們看到 Network Policy,看到它如何幫助我們在 Cluster 裡築起「網路防火牆」。從最簡單的 ingress/egress 控制,到 namespaceSelector
、ipBlock
的進階用法,都能靈活組合,讓 Pod 之間的流量只走「該走的路」,避免服務互相亂竄。
不過在設定這些 Network Policy 的過程裡,一切都繞不開 Label 與 Selector。Service 用 Label 來找到要轉發流量的 Pod,Deployment 用 Label 來維護副本,Network Policy 也靠 Label 來鎖定規則的對象。換句話說,Label 就是 Kubernetes 世界的「身分證」,是所有物件之間建立關聯的基礎。
而 Annotation 雖然不影響排程與選擇,但它像一張「便利貼」,能貼上額外的資訊,方便人或外部工具理解資源的用途、狀態或管理需求。
所以今天,我們就把 Label 與 Annotation 拉出來看看。因為如果沒有這套標籤系統,Kubernetes Cluster 只會是一堆孤立的資源,很難協調合作。
Labels
賦予資源物件一個具有辦識度的 key-value Pair 標籤,前面幾天我們在 Service、Deployment、Network Policy 都用到過它。每個資源物件可以同時擁有多個 Labels (multiple labels)。Kubernetes 幾乎所有資源物件都能加上 label,像是 Pod、Service、Deployment、Namespace,甚至是 Nodes。
👉 它的意義在於:讓 Kubernetes 能透過 selector 把資源彼此關聯起來。
Annotation
和 Label
一樣是 key-value pair,但 不具辨識度,也不會被 Selector 用來篩選。它主要是用來存放額外資訊,例如:
👉 換句話說,Annotation 就像「便利貼」,幫資源多貼一些背景資訊,給人或外部工具使用。
在 yaml 中,我們可以直接在 metadata 區塊加上 labels
標籤:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
labels:
app: myapp
type: back-end
spec:
replicas: 1
selector:
matchLabels:
type: back-end
template:
metadata:
labels:
app: myapp
type: back-end
spec:
containers:
- name: nginx-container
image: nginx
接著就能在 Network Policy 或 Service 中透過 selector
把它連結起來,例如只允許 front-end
的 Pod 存取 back-end
的 Pod。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: myapp-policy
spec:
podSelector:
matchLabels:
type: back-end
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
type: front-end
ports:
- protocol: TCP
port: 8080
除了 yaml 定義外,也可以透過命令式 kubectl label
動態加上、修改或移除。
像是 Node 上常見的標籤:
kubectl get nodes --show-labels
我現在要為我們的 Master Node (kind-control-plane)
加上 env=prod 的 labels,然後 Worker Node 的 Worker1 (kind-worker)
加上 env=dev 的 labels,然後 Worker Node 的 Worker2 (kind-worker2)
加上 env=stage 的 labels。
kubectl label nodes kind-control-plane env=prod
kubectl label nodes kind-worker env=dev
kubectl label nodes kind-worker2 env=stage
使用 -l
做篩選:
查看 env 是 prod 的 Node:
kubectl get nodes --show-labels -l env=prod
查看 env 是非 prod 的 Node:
kubectl get nodes --show-labels -l env!=prod
查看 env 是 Prod 及 Dev 的 Node
kubectl get nodes --show-labels -l "env in (prod,dev)"
查看 env 不是 stage 的 Node
kubectl get nodes --show-labels -l "env notin (stage)"
假設我們現在有五個 Pod,如下圖:
這些查詢方式,讓我們能快速針對一組資源進行操作,不用一個個指定 Pod 名稱,就能一口氣刪除整組。
# 刪除 backend 的 Pod
kubectl delete pods -l type=back-end
# 刪除 frontend 的 Pod
kubectl delete pods -l type=front-end
移除標籤:除了編輯 yaml 檔之外,也可以用命令式 kubectl
來完成。
kubectl label nodes kind-control-plane env-
覆寫標籤:除了編輯 yaml 檔之外,也可以用命令式 kubectl
來完成。
kubectl label nodes kind-worker2 env=test --overwrite
Annotation 與 Label 的寫法幾乎相同,但只用於「描述資訊」。例如:
apiVersion: v1
kind: Pod
metadata:
name: frontend-pod-1
labels:
type: front-end
annotations:
maintainer: "Sean"
git-commit: "a1b2c3d"
spec:
containers:
- name: nginx-container
image: nginx
也能用命令式加上:
kubectl annotate nodes kind-control-plane owner=Sean
這邊分享一下在 Kubernetes 寫 yaml 檔配置的時候,有時候會忘記 Kind
是什麼,或者是他對應的 apiVersion
是什麼版本。但也不用硬背,下方指令可以直接查詢所有 Kubernetes 資源 Kind 與對應的 apiVersion,避免死記硬背。
kubectl api-resources
像是我們實作過的 Deployment
、Service
等等的都可以看到,當然還有超多的物件資源可以查看和瀏覽,所以在編輯 yaml 檔忘記的時候,其實也不用慌張,這個指令就可以看到所有的物件資源!
今天我們把 Label 與 Annotation 拿出來仔細看了一遍:
這些機制看似簡單容易,其實貫穿整個 Kubernetes。沒有它們,Cluster 裡的資源就像沒有名字的群體,彼此無法有效組織。
而明天我們要來看看 Pod 該跑在哪台 Node 上,其實也很關鍵。 GPU Pod 要落在有 GPU 的 Node,資料庫 Pod 不能隨便被排到低效能的 Node。明天我們就來看 Taints & Tolerations、Node Selector、Node Affinity,如何決定 Pod 的最佳落點。而他們同樣也會大量依賴 Label,因為 Pod 到底能不能被排到某台 Node,往往就是透過 Label 與 Selector 來決定的。換句話說,今天的 Label 與 Annotation,就像是明天「排班表」的基礎。